package stack

import (
	. "gitee.com/kingzyt/common/util"
)

//go:generate stackTmplFiller -name=StackInt64 -output=stackInt64 -type=int64
//go:generate stackTmplFiller -name=StackInt32 -output=stackInt32 -type=int32
//go:generate stackTmplFiller -name=StackInt -output=stackInt -type=int
//go:generate stackTmplFiller -name=StackStr -output=stackStr -type=string

type Stack struct {
	list   []interface{}
	topIdx int32
}

func NewStack(initCap int) *Stack {
	if initCap <= 0 {
		initCap = 2
	}
	return &Stack{list: make([]interface{}, initCap)}
}

func (self *Stack) Push(obj interface{}) {
	oldLen := int32(len(self.list))
	if self.topIdx >= oldLen {
		self.topIdx = oldLen
		tempList := make([]interface{}, oldLen*2)
		for i := int32(0); i < oldLen; i++ {
			tempList[i] = self.list[i]
			self.list[i] = nil
		}
		self.list = tempList
	}
	self.list[self.topIdx] = obj
	self.topIdx++
}

func (self *Stack) Pop() interface{} {
	if self.topIdx <= 0 {
		self.topIdx = 0
		return nil
	}
	if self.topIdx >= int32(len(self.list)) {
		self.topIdx = int32(len(self.list))
	}

	self.topIdx--
	return self.list[self.topIdx]
}

func (self *Stack) PeekTop() interface{} {
	if self.topIdx <= 0 {
		return nil
	}
	if self.topIdx > int32(len(self.list)) {
		self.topIdx = int32(len(self.list))
	}
	return self.list[self.topIdx-1]
}

func (self *Stack) Len() int32 {
	return self.topIdx
}

func (self *Stack) IteratorElems(proc func(v interface{}) bool) {
	if proc == nil {
		return
	}

	count := Int32Min(int32(len(self.list)), self.topIdx)
	for i := int32(0); i < count; i++ {
		if !proc(self.list[i]) {
			return
		}
	}
}
func (self *Stack) IteratorRevElems(proc func(v interface{}) bool) {
	if proc == nil {
		return
	}

	count := Int32Min(int32(len(self.list)), self.topIdx)
	for i := count - 1; i >= 0; i-- {
		if !proc(self.list[i]) {
			return
		}
	}
}
